/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = ibmmq_comm.c                                                  */
/*  NOTE      = IBM MQ协议解析共通                                            */
/*  DATE      = 2015/06/03 by wuwk                                            */
/******************************************************************************/
#include <stdio.h>
#include <string.h>

#if defined(FRLINUX4) || defined(FRLINUX5)
    #include "endian_dbg.h"
#else
    #include <endian.h>
#endif

#include "frcomm.h"
#include "ibmmq_charset.h"
#include "ibmmq_comm.h"


/*******************************************************************************
*  FUNC     :  int值解析上报
*  ARGS     :  p_st_body_data(上报链表)
            :  u32_byte_order(数据读取方式)
            :  p_st_data(数据)
            :  p_key(上报key)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int __ibmmq_data_analysis_int(Frreport_body_data *p_st_body_data
                            , Frbyte_Packet *p_st_data
                            , uint32_t u32_byte_order
                            , char *p_key)
{
    uint32_t u32_value = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL || p_key == NULL)
        return FR_FAIL;

    /* int值 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_value, (LITTLE_BIG_ENDIAN)u32_byte_order);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* int值上报 */
    i_ret = frreport_body_l7_add_int(p_st_body_data, p_key, u32_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  long值解析上报
*  ARGS     :  p_st_body_data(上报链表)
            :  u32_byte_order(数据读取方式)
            :  p_st_data(数据)
            :  p_key(上报key)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int __ibmmq_data_analysis_long(Frreport_body_data *p_st_body_data
                             , Frbyte_Packet *p_st_data
                             , uint32_t u32_byte_order
                             , char *p_key)
{
    uint64_t u64_value = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL || p_key == NULL)
        return FR_FAIL;

    /* long值 */
    i_ret = bytebuff_get_long(p_st_data, 8, &u64_value, (LITTLE_BIG_ENDIAN)u32_byte_order);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* long值上报 */
    i_ret = frreport_body_l7_add_long(p_st_body_data, p_key, u64_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  string解析上报
*  ARGS     :  p_st_body_data(上报链表)
            :  u32_byte_order(数据读取方式)
            :  p_st_data(数据)
            :  p_key(上报key)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int __ibmmq_data_analysis_str(Frreport_body_data *p_st_body_data
                            , Frbyte_Packet *p_st_data
                            , uint32_t u32_byte_order
                            , char *p_key
                            , uint32_t u32_ccsid
                            , uint32_t u32_str_len)
{
    char *p_data = NULL;
    char *p_iconv_outbuf = NULL;
    unsigned int ui_iconv_outlen = 0;
    unsigned int ui_report_len = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL || p_key == NULL)
        return FR_FAIL;

    /* 剩余长度不足消息长度, 剩余长度不足要上报的长度 */
    if ((int)u32_str_len > bytebuff_remaining(p_st_data) && bytebuff_remaining(p_st_data) < APM_REPORT_MQ_MAX)
        return APM_L7_ANALYZE_TODO;

    ui_report_len = u32_str_len > (unsigned int)bytebuff_remaining(p_st_data) ? (unsigned int)bytebuff_remaining(p_st_data) : u32_str_len;

    p_data = (char *)frmalloc(ui_report_len + 1);
    if (p_data == NULL)
        return FR_FAIL;
    memset(p_data, 0x00, ui_report_len + 1);

    i_ret = bytebuff_get_bytes(p_st_data, p_data, ui_report_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_data);
        return FR_FAIL;
    }

    if (u32_ccsid != 0)
    {
        /* 转成UTF-8 */
        i_ret = ibmmq_str_to_utf8((short)u32_ccsid, p_data, ui_report_len
                        , &p_iconv_outbuf, &ui_iconv_outlen);
        frfree(p_data);
        if (i_ret == FR_FAIL)
            return FR_FAIL;

        /* 数据上报 */
        if (FRREPORT_BODY_L7_ADD_STR_LIMIT(p_st_body_data, p_key, p_iconv_outbuf) == FR_FAIL)
        {
            frfree(p_iconv_outbuf);
            return FR_FAIL;
        }
        frfree(p_iconv_outbuf);
    }
    else
    {
        /* 数据上报 */
        if (FRREPORT_BODY_L7_ADD_STR_LIMIT(p_st_body_data, p_key, p_data) == FR_FAIL)
        {
            frfree(p_data);
            return FR_FAIL;
        }
        frfree(p_data);
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  binary解析上报
*  ARGS     :  p_st_body_data(上报链表)
            :  u32_byte_order(数据读取方式)
            :  p_st_data(数据)
            :  p_key(上报key)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int __ibmmq_data_analysis_bin(Frreport_body_data *p_st_body_data
                            , Frbyte_Packet *p_st_data
                            , uint32_t u32_byte_order
                            , char *p_key
                            , uint32_t u32_str_len)
{
    char *p_data = NULL;
    unsigned int ui_report_len = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL || p_key == NULL)
        return FR_FAIL;

    /* 剩余长度不足消息长度, 剩余长度不足要上报的长度 */
    if ((int)u32_str_len > bytebuff_remaining(p_st_data) && bytebuff_remaining(p_st_data) < APM_REPORT_MQ_MAX)
        return APM_L7_ANALYZE_TODO;

    ui_report_len = u32_str_len > (unsigned int)bytebuff_remaining(p_st_data) ? (unsigned int)bytebuff_remaining(p_st_data) : u32_str_len;

    p_data = (char *)frmalloc(ui_report_len + 1);
    if (p_data == NULL)
        return FR_FAIL;
    memset(p_data, 0x00, ui_report_len + 1);

    i_ret = bytebuff_get_bytes(p_st_data, p_data, ui_report_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_data);
        return FR_FAIL;
    }

    /* 数据上报 */
    i_ret = frreport_body_l7_add_bin(p_st_body_data, p_key, p_data, ui_report_len);
    frfree(p_data);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  int list解析上报
*  ARGS     :  p_st_body_data(上报链表)
            :  u32_byte_order(数据读取方式)
            :  p_st_data(数据)
            :  p_key(上报key)
            :  i_cnt(list个数)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int __ibmmq_data_analysis_intlist(Frreport_body_data *p_st_body_data
                            , Frbyte_Packet *p_st_data
                            , uint32_t u32_byte_order
                            , char *p_key
                            , int i_cnt)
{
    char *p_value = NULL;
    char arr_tmp[11];
    uint32_t u32_value = 0;
    int i_buffsize = 0;
    int i_usedsize = 0;
    int i = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buffsize = i_cnt*11 + 2;
    p_value = (char *)frmalloc(i_buffsize);
    if (p_value == NULL)
        return FR_FAIL;
    memset(p_value, 0x00, i_buffsize);

    strcpy(p_value, "[");
    i_usedsize += 1;
    for (; i < i_cnt; i++)
    {
        /* int值 */
        i_ret = bytebuff_get_int(p_st_data, 4, &u32_value, (LITTLE_BIG_ENDIAN)u32_byte_order);
        if (i_ret == FR_FAIL)
        {
            frfree(p_value);
            return FR_FAIL;
        }

        snprintf(arr_tmp, sizeof(arr_tmp), "%d", u32_value);
        if (i != i_cnt - 1)
            snprintf(p_value + i_usedsize, i_buffsize - i_usedsize, "%s,", arr_tmp);
        else
            snprintf(p_value + i_usedsize, i_buffsize - i_usedsize, "%s]", arr_tmp);

        i_usedsize += (strlen(arr_tmp)+1);
    }

    i_ret = frreport_body_l7_add_str(p_st_body_data, p_key, p_value);
    if (i_ret == FR_FAIL)
    {
        frfree(p_value);
        return FR_FAIL;
    }

    frfree(p_value);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  string list解析上报
*  ARGS     :  p_st_body_data(上报链表)
            :  u32_byte_order(数据读取方式)
            :  p_st_data(数据)
            :  p_key(上报key)
            :  i_cnt(list个数)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int __ibmmq_data_analysis_stringlist(Frreport_body_data *p_st_body_data
                            , Frbyte_Packet *p_st_data
                            , uint32_t u32_byte_order
                            , char *p_key
                            , uint32_t u32_ccsid
                            , uint32_t u32_str_len
                            , int i_cnt)
{
    char *p_value = NULL;
    char *p_data = NULL;
    int i_data_len = 0;
    int i_buffsize = 0;
    int i_usedsize = 0;
    int i = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL || p_key == NULL)
        return FR_FAIL;

    /* 剩余长度不足消息长度, 剩余长度不足要上报的长度 */
    if ((int)(i_cnt*u32_str_len) > bytebuff_remaining(p_st_data) && bytebuff_remaining(p_st_data) < APM_REPORT_MQ_MAX)
        return APM_L7_ANALYZE_TODO;

    i_data_len = (int)(i_cnt*u32_str_len) > bytebuff_remaining(p_st_data) ? bytebuff_remaining(p_st_data) : (int)(i_cnt*u32_str_len);

    p_data = (char *)frmalloc(u32_str_len+1);
    if (p_data == NULL)
        return FR_FAIL;

    i_buffsize = (int)(i_cnt*u32_str_len) > bytebuff_remaining(p_st_data) ? (bytebuff_remaining(p_st_data)+i_cnt*3+3) : (int)(i_cnt*(u32_str_len+3) + 2);
    p_value = (char *)frmalloc(i_buffsize);
    if (p_value == NULL)
    {
        frfree(p_data);
        return FR_FAIL;
    }
    memset(p_value, 0x00, i_buffsize);

    strcpy(p_value, "[");
    i_usedsize += 1;

    for (; i < i_cnt; i++)
    {
        memset(p_data, 0x00, u32_str_len+1);
        /* string */
        i_ret = bytebuff_get_bytes(p_st_data, p_data, u32_str_len);
        if (i_ret == FR_FAIL)
        {
            frfree(p_data);
            frfree(p_value);
            return FR_FAIL;
        }

        if (i != i_cnt - 1)
            snprintf(p_value + i_usedsize, i_buffsize - i_usedsize, "\"%s\",", p_data);
        else
            snprintf(p_value + i_usedsize, i_buffsize - i_usedsize, "\"%s\"]", p_data);

        i_usedsize += (u32_str_len+3);
    }

    frfree(p_data);
    i_ret = frreport_body_l7_add_str(p_st_body_data, p_key, p_value);
    if (i_ret == FR_FAIL)
    {
        frfree(p_value);
        return FR_FAIL;
    }

    frfree(p_value);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  添加queue到链表
*  ARGS     :  p_lst_queue(queue链表)
            :  p_queue(队列名)
            :  u32_hdl(Hdl)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int ibmmq_queue_list_add(L7Session_ibmmq *p_st_session, char *p_queue, uint32_t u32_hdl)
{
    Queue_lst_ibmmq *p_lst_queue = NULL;
    Queue_lst_ibmmq *p_lst_queue_new = NULL;

    if (p_st_session == NULL || p_queue == NULL)
        return FR_FAIL;

    p_lst_queue = p_st_session->p_lst_queue;

    p_lst_queue_new = (Queue_lst_ibmmq *)frmalloc(sizeof(Queue_lst_ibmmq));
    if (p_lst_queue_new == NULL)
        return FR_FAIL;

    memset(p_lst_queue_new, 0x00, sizeof(Queue_lst_ibmmq));
    strcpy(p_lst_queue_new->arr_queue, p_queue);
    p_lst_queue_new->u32_hdl = u32_hdl;

    if (p_lst_queue == NULL)
    {
        p_st_session->p_lst_queue = p_lst_queue_new;
        return FR_SUCC;
    }

    while(1)
    {
        if (p_lst_queue->next)
            p_lst_queue = p_lst_queue->next;
        else
            break;
    }

    p_lst_queue->next = p_lst_queue_new;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  用队列名在队列链表里查找
*  ARGS     :  p_lst_queue(queue链表)
            :  p_queue(队列名)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
Queue_lst_ibmmq *ibmmq_queue_list_queue_find(Queue_lst_ibmmq *p_lst_queue, char *p_queue)
{
    Queue_lst_ibmmq *p_st_queue = NULL;

    if (p_lst_queue == NULL || p_queue == NULL)
        return NULL;

    p_st_queue = p_lst_queue;
    while (p_st_queue)
    {
        if (strcmp(p_st_queue->arr_queue, p_queue) == 0)
            break;
        p_st_queue = p_st_queue->next;
    }

    return p_st_queue;
}

/*******************************************************************************
*  FUNC     :  用Hdl在队列链表里查找
*  ARGS     :  p_lst_queue(queue链表)
            :  u32_hdl(Hdl)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
Queue_lst_ibmmq *ibmmq_queue_list_hdl_find(Queue_lst_ibmmq *p_lst_queue, uint32_t u32_hdl)
{
    Queue_lst_ibmmq *p_st_queue = NULL;

    if (p_lst_queue == NULL)
        return NULL;

    p_st_queue = p_lst_queue;
    while (p_st_queue)
    {
        if (u32_hdl == p_st_queue->u32_hdl)
            break;
        p_st_queue = p_st_queue->next;
    }

    return p_st_queue;
}

/*******************************************************************************
*  FUNC     :  用Hdl在队列链表里删除对应节点
*  ARGS     :  p_lst_queue(queue链表)
            :  u32_hdl(Hdl)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
int ibmmq_queue_list_hdl_del(Queue_lst_ibmmq **pp_lst_queue, uint32_t u32_hdl)
{
    Queue_lst_ibmmq *p_st_queue = NULL;
    Queue_lst_ibmmq *p_st_queue_pre = NULL;

    if (pp_lst_queue == NULL)
        return FR_FAIL;

    p_st_queue = *pp_lst_queue;
    while (p_st_queue)
    {
        if (u32_hdl == p_st_queue->u32_hdl)
            break;
        p_st_queue_pre = p_st_queue;
        p_st_queue = p_st_queue->next;
    }

    if (p_st_queue == NULL)
        return FR_SUCC;

    /* 首节点 */
    if (p_st_queue_pre == NULL)
    {
        *pp_lst_queue = p_st_queue->next;
        frfree(p_st_queue);
    }
    else
    {
        p_st_queue_pre->next = p_st_queue->next;
        frfree(p_st_queue);
    }

    return FR_SUCC;
}
